﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;

namespace ETRoboConResultEditorExcel
{
    public partial class Sheet1
    {
        private void Sheet1_Startup(object sender, System.EventArgs e)
        {
            int col = POS_BonusResultStartCol;
            while (true)
            {
                if (((Excel.Range)Cells[POS_EntryRow, col]).Value2 == null)
                {
                    break;
                }
                string sc = ((Excel.Range)Cells[POS_EntryRow, col]).Value2.ToString();
                _bonusResultCols.Add(sc, col);
                col++;
            }
            _showing = false;
        }

        private void Sheet1_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO で生成されたコード

        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InternalStartup()
        {
            this.Shutdown += new System.EventHandler(this.Sheet1_Shutdown);
            this.Startup += new System.EventHandler(this.Sheet1_Startup);
            this.Change += new Microsoft.Office.Interop.Excel.DocEvents_ChangeEventHandler(this.Sheet1_Change);

        }

        #endregion

        public int TurnTotalNo { get; set; }

        private const int POS_ContestCol = 2;
        private const int POS_ContestRow = 1;
        private const int POS_GameRow = 2;

        private const int POS_EntryRow = 4;
        private const int POS_RoundNoCol = 1;
        private const int POS_TurnNoCol = 2;
        private const int POS_EntryTeamIDCol = 3;
        private const int POS_BibCol = 4;
        private const int POS_TeamNameCol = 5;
        private const int POS_CourseCol = 6;
        private const int POS_StatusCol = 7;
        private const int POS_RunTimeCol = 8;
        private const int POS_RunPointCol = 9;

        private const int POS_BonusResultStartCol = 10;
        
        private Dictionary<string, int> _bonusResultCols = new Dictionary<string, int>();
        private bool _showing;

        public void LoadBonusSpecs(string[] bsShortKeys)
        {
            for (int i = 0; i < bsShortKeys.Length; i++)
            {
                _bonusResultCols.Add(bsShortKeys[i], POS_BonusResultStartCol + i);
                ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow, POS_BonusResultStartCol + i]).Value2 = bsShortKeys[i];
                var style = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow, 1]).Style;
            }
        }

        public void ReverseResultEditing(int roundNo)
        {
            int index = 1;
            if (roundNo == 2)
            {
                while (true)
                {
                    var value =
                    ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_RoundNoCol]).Value2;
                    if (value != null)
                    {
                        int no = System.Convert.ToInt32(value);
                        if (no == roundNo)
                        {
                            break;
                        }
                    }
                    else
                    {
                        return;
                    }
                    index++;
                }
            }
            while (true)
            {
                var value = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_RoundNoCol]).Value2;
                if (value == null)
                {
                    return;
                }
                int no = System.Convert.ToInt32(value);
                if (no != roundNo)
                {
                    return;
                }
                var upperRT = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_RunTimeCol]).Value2;
                var lowerRT = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index + 1, POS_RunTimeCol]).Value2;
                ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_RunTimeCol]).Value2 = lowerRT;
                ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index + 1, POS_RunTimeCol]).Value2 = upperRT;
                var upperRR = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_StatusCol]).Value2;
                var lowerRR = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index + 1, POS_StatusCol]).Value2;
                ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_StatusCol]).Value2 = lowerRR;
                ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index + 1, POS_StatusCol]).Value2 = upperRR;
                for (int c = 0; c < _bonusResultCols.Count; c++)
                {
                    var upper = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_BonusResultStartCol + c]).Value2;
                    var lower = ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index + 1, POS_BonusResultStartCol + c]).Value2;
                    ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index, POS_BonusResultStartCol + c]).Value2 = lower;
                    ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index + 1, POS_BonusResultStartCol + c]).Value2 = upper;
                    
                }
                index++;
                index++;
               // ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index++, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2 = "D";
               // ((Excel.Range)Globals.Sheet1.Cells[POS_EntryRow + index++, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2 = "D";
            }
        }

        public void SetTurnInfo(int roundNo, int turnNo, int entryTeamId, int bib, string teamName, string cource)
        {
            int row = POS_EntryRow;
            if (roundNo == 2)
            {
                row += TurnTotalNo * 2;
            }
            int mod = 0;
            if (cource.CompareTo("OUT") == 0)
            {
                mod = 1;
            }
            int currentRow = row + turnNo * 2 + mod - 1;
            ((Excel.Range)Cells[currentRow, POS_RoundNoCol]).Value2 = roundNo;
            ((Excel.Range)Cells[currentRow, POS_TurnNoCol]).Value2 = turnNo;
            ((Excel.Range)Cells[currentRow, POS_EntryTeamIDCol]).Value2 = entryTeamId.ToString();
            ((Excel.Range)Cells[currentRow, POS_BibCol]).Value2 = bib;
            ((Excel.Range)Cells[currentRow, POS_TeamNameCol]).Value2 = teamName;
            ((Excel.Range)Cells[currentRow, POS_CourseCol]).Value2 = cource;
        }

        public void SetRunnerResults(int roundNo, int turnNo, int entryTeamId, ETRoboConRM.RunnerStatus status, int? runTime, int? runPoint, string[] bonusResults)
        {
            int row = FindTurnRunnerRowEntry(roundNo, turnNo, entryTeamId);
            for (int i = 0; i < _bonusResultCols.Count; i++)
            {
                ((Excel.Range)Cells[row, POS_BonusResultStartCol + i]).Value2 = "";
            }
            ((Excel.Range)Cells[row, POS_StatusCol]).Value2 = status.ToString();
            ((Excel.Range)Cells[row, POS_RunTimeCol]).Value2 = runTime;
            ((Excel.Range)Cells[row, POS_RunPointCol]).Value2 = runPoint;
            if (bonusResults != null)
            {
                foreach (string bonusResult in bonusResults)
                {
                    int col = _bonusResultCols[bonusResult];
                    ((Excel.Range)Cells[row, col]).Value2 = @"OK";

                }
            }
        }

        public void SetRunnerPoint(int index,int runnerPoint)
        {
            ((Excel.Range)Cells[POS_EntryRow + index, POS_RunPointCol]).Value2 = runnerPoint;
        }

        private int FindTurnRunnerRowEntry(int roundNo, int turnNo, int entryTeamId)
        {
            int result = 0;

            int totalNo = Globals.Sheet2.GetEntryTeamTotalNo();
            for (int i = 1; i <= 2 * totalNo; i++)
            {
                int index = i;
                string rNo = ((Excel.Range)Cells[POS_EntryRow + index, POS_RoundNoCol]).Value2.ToString();
                string tNo = ((Excel.Range)Cells[POS_EntryRow + index, POS_TurnNoCol]).Value2.ToString();
                string etId = ((Excel.Range)Cells[POS_EntryRow + index, POS_EntryTeamIDCol]).Value2.ToString();
                if (roundNo.ToString().CompareTo(rNo) == 0 && turnNo.ToString().CompareTo(tNo) == 0 && entryTeamId.ToString().CompareTo(etId) == 0)
                {
                    result = i+POS_EntryRow;
                    break;
                }
            }
            return result;
        }

        public void SetGameInfo(string contest, string game)
        {
            ((Excel.Range)Cells[POS_ContestRow, POS_ContestCol]).Value2 = contest;
            ((Excel.Range)Cells[POS_GameRow, POS_ContestCol]).Value2 = game;
        }

        public void StartShow()
        {
            _showing = true;
            ClearDurtiyStatus();
        }
        public void EndShow()
        {
            _showing = false;
        }

        public void ClearDurtiyStatus()
        {
            int totalETNum = Globals.Sheet2.GetEntryTeamTotalNo();
            for (int i = 1; i <= 2 * totalETNum; i++)
            {
                ((Excel.Range)Cells[POS_EntryRow + i, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2 = "";
            }
        }

        private void Sheet1_Change(Microsoft.Office.Interop.Excel.Range Target)
        {
            if (_showing)
            {
                return;
            }
            int row = Target.Row;
            int col = Target.Column;
            string prev = Target.Previous.Value2.ToString();
            string orig = ((Excel.Range)Cells[row, col]).Value2.ToString();
            if (row > POS_EntryRow && col <= POS_BonusResultStartCol + _bonusResultCols.Count - 1)
            {
                if (col == POS_RunTimeCol || col == POS_RunPointCol)
                {
                    int time;
                    if (!Int32.TryParse(((Excel.Range)Cells[row, col]).Value2.ToString(), out time))
                    {
                        MessageBox.Show("RunTime and RunPoint should be integer number by 0.1 sec!");
                        ((Excel.Range)Cells[row, col]).Value2 = prev;
                        return;
                    }
                }
                if (col == POS_StatusCol)
                {
                    string status = ((Excel.Range)Cells[row, col]).Value2.ToString();
                    if (status.CompareTo("DECLINED") != 0 && status.CompareTo("COMPLETED") != 0 && status.CompareTo("READY") == 0 && status.CompareTo("RETIRED") != 0 && status.CompareTo("OBSTRUCTED") != 0)
                    {
                        MessageBox.Show("Status should be READY|COMPLETED|RETIRED|OBSTRUCTED|DECLINED");
                        ((Excel.Range)Cells[row, col]).Value2 = prev;
                        return;
                    }
                    if (status.CompareTo("DECLINED") == 0 || status.CompareTo("RETIRED") == 0 || status.CompareTo("OBSTRUCTED") == 0)
                    {
                        ((Excel.Range)Cells[row, POS_RunTimeCol]).Value2 = 1200;
                        ((Excel.Range)Cells[row, POS_RunPointCol]).Value2 = 1200;
                            ClearAllBonusResults(row);
                        if (status.CompareTo("RETIRED") == 0)
                        {
                            //                            int[] brCols = {
                            //                                             _bonusResultCols["GG"],
                            //                                           _bonusResultCols["GI"]
                            //                                     };
                            //                    for (int brCol = 0; brCol < brCols.Length; brCol++)
                            //                  {
                            //                    ((Excel.Range)Cells[row, POS_BonusResultStartCol + brCol]).Value2 = "";
                            //              }
                            //            ((Excel.Range)Cells[row, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2 = @"D";
                        }
                    }
                    if (status.CompareTo("READY") == 0)
                    {
                        MessageBox.Show("Current version doesn't support READY");
//                        ((Excel.Range)Cells[row, POS_RunTimeCol]).Value2 = null;
  //                      ((Excel.Range)Cells[row, POS_RunPointCol]).Value2 = null;
    //                    ClearAllBonusResults(row);
                    }
                    if (status.CompareTo("COMPLETED") == 0)
                    {
//                        int[] brCols = {
  //                                         _bonusResultCols["MG"],
    //                                       _bonusResultCols["GG"]
      //                                 };
        //                for (int brCol = 0; brCol < brCols.Length; brCol++)
          //              {
            //                ((Excel.Range)Cells[row, POS_BonusResultStartCol + brCols[brCol]]).Value2 = @"OK";
              //          }
                    }
                }
                if (POS_BonusResultStartCol <= col && col < POS_BonusResultStartCol + _bonusResultCols.Count)
                {
                    string spec = ((Excel.Range)Cells[row, col]).Value2.ToString();
                    if (spec.CompareTo("OK") != 0 && spec.CompareTo("NG") != 0)
                    {
                        MessageBox.Show("Bonus Results should be 'OK' or 'NG'!");
                        ((Excel.Range)Cells[row, col]).Value2 = prev;
                        return;
                    }
                }
                ((Excel.Range)Cells[row, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2 = @"D";
            }
        }

        private void ClearAllBonusResults(int row)
        {
            for (int i = 0; i < _bonusResultCols.Count; i++)
            {
                ((Excel.Range)Cells[row, POS_BonusResultStartCol + i]).Value2 = null;
            }
        }

        public IEnumerable<int> GetTurnRunnerIndex()
        {
            int totalNo= Globals.Sheet2.GetEntryTeamTotalNo();
            for (int i=1;i<=totalNo*2;i++){
                if (((Excel.Range)Cells[POS_EntryRow + i, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2 != null)
                {
                    if (((Excel.Range)Cells[POS_EntryRow + i, POS_BonusResultStartCol + _bonusResultCols.Count]).Value2.ToString().CompareTo(@"D") == 0)
                    {
                        yield return i;
                    }
                }
            }
        }

        public void GetTurnRunnerResults(int rowIndex, out int roundId, out int turnNo, out string entryTeamId, out string cource, out string status, out int runTime, out string[] bonusResults)
        {
            string rNo = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_RoundNoCol]).Value2.ToString();
            string tNo = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_TurnNoCol]).Value2.ToString();
            entryTeamId = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_EntryTeamIDCol]).Value2.ToString();
            string rTime = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_RunTimeCol]).Value2.ToString();
            status = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_StatusCol]).Value2.ToString();
            cource = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_CourseCol]).Value2.ToString();
            Int32.TryParse(rNo,out roundId);
            Int32.TryParse(tNo,out turnNo);
            Int32.TryParse(rTime, out runTime);
            List<string> brs = new List<string>();
            for (int i = 0; i < _bonusResultCols.Count; i++)
            {
                if (((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_BonusResultStartCol + i]).Value2 != null)
                {
                    string res = ((Excel.Range)Cells[POS_EntryRow + rowIndex, POS_BonusResultStartCol + i]).Value2.ToString();
                    if (res.CompareTo(@"OK") == 0)
                    {
                        brs.Add(((Excel.Range)Cells[POS_EntryRow, POS_BonusResultStartCol + i]).Value2.ToString());
                    }
                }
            }
            bonusResults = brs.ToArray();
        }

        public bool GetTeamResult(int bib, string couse, out string name,out int runTime, out string[] bonus)
        {
            name = "";
            runTime = 0;
            bonus = null;
            bool existed = false;
            int index = POS_EntryRow + 1;
            while (true)
            {
                object bibValue = ((Excel.Range)Cells[index, POS_BibCol]).Value2;
                if (bibValue==null)
                {
                    break;
                }
                int cBib = int.Parse(bibValue.ToString());
                if (bib == cBib)
                {
                    string cCouse = ((Excel.Range)Cells[index, POS_CourseCol]).Value2.ToString();
                    if (couse.CompareTo(cCouse) == 0)
                    {
                        existed = true;
                        name = ((Excel.Range)Cells[index, POS_TeamNameCol]).Value2.ToString();
                        string runTimeStr = ((Excel.Range)Cells[index, POS_RunTimeCol]).Value2.ToString();
                        runTime = int.Parse(runTimeStr);
                        var bonusIndex = new Dictionary<string, int>();
                        bonusIndex.Add("MC", 11);
                        bonusIndex.Add("SST", 12);
                        bonusIndex.Add("SSS", 13);
                        bonusIndex.Add("ST", 14);
                        bonusIndex.Add("GI", 16);
                        var bonusResults = new List<string>();
                        foreach (var colKey in bonusIndex.Keys)
                        {
                            if (((Excel.Range)Cells[index, bonusIndex[colKey]]).Value2 != null)
                            {
                                string bonusStmt = ((Excel.Range)Cells[index, bonusIndex[colKey]]).Value2.ToString();
                                if (bonusStmt.CompareTo("OK") == 0)
                                {
                                    bonusResults.Add(colKey);
                                }
                            }
                        }
                        bonus = bonusResults.ToArray();
                        break;
                    }
                }
                index++;
            }
            return existed;
        }
    }
}
